/***********************************************************
 *  File_Name  : XJCurl.cpp
 *  File_Path   : 
 *  File_Encode : UTF8
 *  Description : CURL操作类
 *  
 *  OS : Linux, UNIX,Windows,Other
 *  LastVersion  : 20120829
 *      
 *  Author      : LiXiujie(李秀杰)
 *  Date        : 2011-8-29
 *  Version     : 20120829
 *  Description : 
 *                
 *  Edit Author : 
 *  Edit Date   : 
 *  Version     : 
 *  Description :
 *                
 ***********************************************************/

#include "XJCurl.h"
#include <curl/curl.h>

namespace XJUtilClass{
XJCurl::XJCurl() {
	// TODO Auto-generated constructor stub
}

XJCurl::~XJCurl() {
	// TODO Auto-generated destructor stub
}

XJCurlBuf * XJCurl::XJCurlBufCreate(){
	XJCurlBuf *buf = (XJCurlBuf *)malloc(sizeof(XJCurlBuf));
	memset(buf, 0, sizeof(XJCurlBuf));
	buf->nMaxSize = 1024;
	buf->pData =  (char *)malloc(buf->nMaxSize);
	memset(buf->pData, 0, buf->nMaxSize);
	return buf;
}

void XJCurl::XJCurlBufDelete(XJCurlBuf * buf){
	if (buf->pData != NULL){
		free(buf->pData);
	}
	free(buf);
}


size_t XJCurl::my_curl_fwrite(void *buffer, size_t size, size_t nmemb, void *stream)
{
	size_t sizes = size*nmemb;
	//printf((char *)buffer);
	XJCurlBuf *out=(XJCurlBuf *)stream;
	if(out && !out->pData) {
		out->nSize = 0;
		out->nMaxSize = sizes+1;
		out->pData = (char *)malloc(out->nMaxSize);
	}
	if (sizes + out->nSize >= out->nMaxSize){
		out->nMaxSize = out->nSize + sizes + 1;
		out->pData = (char *)realloc(out->pData, out->nMaxSize);
	}
	memcpy(out->pData+out->nSize, buffer, sizes);
	out->nSize += sizes;
	out->pData[out->nSize] = '\0';
	return sizes;
}
int XJCurl::XJGetHtml(XJCurlBuf *buf, const char *szURL){
	memset(buf->pData, 0, buf->nMaxSize);
	CURL *curl;
	CURLcode res;
	curl = curl_easy_init();
	if(curl) {
		struct curl_slist* head = NULL;
		std::map<std::string, std::string>::iterator it = m_mapHeadValue.begin();
		while (it != m_mapHeadValue.end()){
			std::string strHeadValue = it->first;
			strHeadValue = strHeadValue + ": "+it->second;
			head = curl_slist_append(head, strHeadValue.c_str());
			it++;
		}
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, head);
#ifdef __DEBUG__
		curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);
		//curl_easy_setopt(curl, CURLOPT_STDERR, 1L);
#endif

		curl_easy_setopt(curl, CURLOPT_URL, szURL);
		//curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_curl_fwrite);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, buf);
		//curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
		CommonSetOpt((void *)curl);
		res = curl_easy_perform(curl);
		/* always cleanup */
		curl_easy_cleanup(curl);
		curl_slist_free_all(head);

	}else{
		 res = CURLE_FAILED_INIT;
	}
	return res;
}

int XJCurl::XJPostHtml(XJCurlBuf *buf, const char *szURL, const char *szPostData){
	memset(buf->pData, 0, buf->nMaxSize);
	CURL *curl;
	CURLcode res;
	curl = curl_easy_init();
	if(curl) {
		struct curl_slist* head = NULL;
		std::map<std::string, std::string>::iterator it = m_mapHeadValue.begin();
		while (it != m_mapHeadValue.end()){
			std::string strHeadValue = it->first;
			strHeadValue = strHeadValue + ": "+it->second;
			head = curl_slist_append(head, strHeadValue.c_str());
			it++;
		}
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, head);

		curl_easy_setopt(curl, CURLOPT_URL, szURL);
		if (szPostData != NULL){
			curl_easy_setopt(curl, CURLOPT_POST,1L);
			curl_easy_setopt(curl, CURLOPT_POSTFIELDS, szPostData);
		}
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_curl_fwrite);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, buf);
		//curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
		CommonSetOpt((void *)curl);
		res = curl_easy_perform(curl);
		/* always cleanup */
		curl_easy_cleanup(curl);
		curl_slist_free_all(head);
	}else{
		 res = CURLE_FAILED_INIT;
	}
	return res;
}

int XJCurl::XJPutHtml(XJCurlBuf *buf, const char *szURL){
	memset(buf->pData, 0, buf->nMaxSize);
	CURL *curl;
	CURLcode res;
	curl = curl_easy_init();
	if(curl) {
		struct curl_slist* head = NULL;
		std::map<std::string, std::string>::iterator it = m_mapHeadValue.begin();
		while (it != m_mapHeadValue.end()){
			std::string strHeadValue = it->first;
			strHeadValue = strHeadValue + ": "+it->second;
			head = curl_slist_append(head, strHeadValue.c_str());
			it++;
		}
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, head);
		curl_easy_setopt(curl, CURLOPT_URL, szURL);
		//curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_curl_fwrite);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, buf);
		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
		CommonSetOpt((void *)curl);
		res = curl_easy_perform(curl);
		/* always cleanup */
		curl_easy_cleanup(curl);
		curl_slist_free_all(head);
	}else{
		 res = CURLE_FAILED_INIT;
	}
	return res;
}

int XJCurl::XJDeleteHtml(XJCurlBuf *buf, const char *szURL){
	memset(buf->pData, 0, buf->nMaxSize);
	CURL *curl;
	CURLcode res;
	curl = curl_easy_init();
	if(curl) {
		struct curl_slist* head = NULL;
		std::map<std::string, std::string>::iterator it = m_mapHeadValue.begin();
		while (it != m_mapHeadValue.end()){
			std::string strHeadValue = it->first;
			strHeadValue = strHeadValue + ": "+it->second;
			head = curl_slist_append(head, strHeadValue.c_str());
			it++;
		}
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, head);
		curl_easy_setopt(curl, CURLOPT_URL, szURL);
		//curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postthis);
		curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_curl_fwrite);
		curl_easy_setopt(curl, CURLOPT_WRITEDATA, buf);
		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
		curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
		CommonSetOpt((void *)curl);
		res = curl_easy_perform(curl);
		/* always cleanup */
		curl_easy_cleanup(curl);
		curl_slist_free_all(head);
	}else{
		 res = CURLE_FAILED_INIT;
	}
	return res;
}

int XJCurl::XJAddHeadValue(const std::string strName,const std::string strValue){
	m_mapHeadValue[strName] = strValue;
	return 0;
}

int XJCurl::XJDelHeadValue(const std::string strName){
	std::map<std::string, std::string>::iterator it;
	it = m_mapHeadValue.find(strName);
	if (it != m_mapHeadValue.end()){
		m_mapHeadValue.erase(it);
		return 0;
	}
	return -1;
}

int XJCurl::XJCleanHeadValue(){
	m_mapHeadValue.clear();
	return 0;
}

void XJCurl::XJSetCookiePath(const std::string &strCookiePath){
	m_strCookiePath = strCookiePath;
}

std::string XJCurl::XJGetCookiePath(){
	return m_strCookiePath;
}

void XJCurl::CommonSetOpt(void *pCurl){
	CURL *curl = (CURL *)pCurl;
	if (m_strCookiePath.size()){
		curl_easy_setopt(curl, CURLOPT_COOKIEFILE, m_strCookiePath.c_str());
		curl_easy_setopt(curl, CURLOPT_COOKIEJAR, m_strCookiePath.c_str());
	}
}
std::string XJCurl::XJEscape(const std::string &strFieldValue){
	CURL *curl;
	curl = curl_easy_init();
	if(curl) {
		char *szData = curl_easy_escape(curl, strFieldValue.c_str(), strFieldValue.length());
		if (szData){
			std::string strData = szData;
			curl_free(szData);
			curl_easy_cleanup(curl);
			return strData;
		}
		curl_easy_cleanup(curl);
	}
	return std::string();
}
std::string XJCurl::XJUnescape(const std::string &strFieldValue){
	int nLen = 0;
	CURL *curl;
	curl = curl_easy_init();
	if(curl) {
		char *szData = curl_easy_unescape(curl, strFieldValue.c_str(), strFieldValue.size(), &nLen);
		if (szData){
			std::string strData = szData;
			curl_free(szData);
			curl_easy_cleanup(curl);
			return strData;
		}
		curl_easy_cleanup(curl);
	}
	return std::string();
}
} //namespace XJUtilClass
